#include "cirSinglyListOps.h"

Node* NewNode(DataType nodeData) {
    Node *newNode = malloc(sizeof(Node));
    assert(newNode != NULL);
    newNode->data = nodeData;
    newNode->link = NULL;

    return newNode;
}

short isEmpty(CirSglList *list) {
    if (list->lenth == 0) {
        return -1;
    } else {
        return 0;
    }
}

void initList(CirSglList *list) {
    Node *head = malloc(sizeof(Node));
    assert(head != NULL);
    list->first = list->last = head;
    list->last->link = list->first;
    list->lenth = 0;
}

// case 1
void displayList(CirSglList *list) {
    if (isEmpty(list)) {
        printf("Nothing in an empty list.\n");
        return;
    }

    Node *tmpNode = list->first->link;

    while (tmpNode->link != list->first) {
        printf("%d -- ", tmpNode->data);
        tmpNode = tmpNode->link;
    }
    printf("%d.\n", tmpNode->data);
}

// case 2
short insertAtTheEnd(CirSglList *list, DataType insertData) {
    Node *insertNode = NewNode(insertData);

    list->last->link = insertNode;
    list->last = insertNode;
    list->last->link = list->first;
    list->lenth++;

    return 0;
}

// case 3
short insertAtTheBeginning(CirSglList *list, DataType insertData) {
    Node *insertNode = NewNode(insertData);

    insertNode->link = list->first->link;
    list->first->link = insertNode;
    list->lenth++;

    if (list->lenth == 1) {
        list->last = insertNode;
    }

    return 0;
}

// case 4
short insertToOrderedList(CirSglList *list, DataType insertData) {
    Node *insertNode = NewNode(insertData);
    Node *tmpNode = list->first;

    while (tmpNode->link->data < insertData && tmpNode != list->first) {
        tmpNode = tmpNode->link;
    }
    insertNode->link = tmpNode->link;
    tmpNode->link = insertNode;
    list->lenth++;

    return 0;
}

// case 5
int getLenth(CirSglList *list) {
    return list->lenth;
}

// case 7
short deleteLastData(CirSglList *list) {
    if (isEmpty(list)) return -1;

    Node *delNodePrior = list->first;

    // 找到最后一个结点的前驱
    while (delNodePrior->link != list->last) {
        delNodePrior = delNodePrior->link;
    }

    free(delNodePrior->link);
    list->last = delNodePrior;
    list->last->link = list->first;
    list->lenth--;

    return 0;
}

// case 8
short deleteFirstData(CirSglList *list) {
    if (isEmpty(list)) return -1;

    Node *delNode = list->first->link;

    list->first->link = delNode->link;
    free(delNode);
    list->lenth--;

    if (list->lenth == 0) {
        list->last = list->first;
    }

    return 0;
}